package tests;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

import bitmap.InstantiateColumnarFile;
import bitmap.KeyClass;
import btree.IntegerKey;
import btree.StringKey;
import columnar.ColumnarFileInfo;
import columnar.Columnarfile;
import diskmgr.pcounter;
import global.AttrType;
import global.IndexType;
import global.Size;
import global.SystemDefs;
import global.TupleOrder;
import heap.Heapfile;
import heap.Tuple;
import index.ColumnarIndexScan;
import index.Helper;
import iterator.ColumnarDuplElim;
import iterator.ColumnarSort;

public class Driver {

	
	
	private static Columnarfile f = null;
	private static AttrType[] types;
	
	private static String []colNames;
	private static String columnDbName;
	private static String columnarFileName;
	private static ArrayList <String> columnNames=new ArrayList<String>();
	private static String accessType;
	private static String valueConstraint;
	private static String numBuf;
	private static String columnName;
	private static String operator;
	private static String columnValue;
	private static String dbName;
	private static String noOfCols;
	private static String batchInsertFileName;
	private static KeyClass value=null;
	private static int columnIndex=0;
	private static int choice = 0;
	private static SystemDefs sysdef;
	private static ColumnarFileInfo cInfo;
	private static ColumnarBitmapEquiJoins cJoin;
	/**
	 * @param args
	 */
	
	public static void parseValue(String tempValue)
	{
		StringTokenizer st = new StringTokenizer(tempValue, ":");
		System.out.println("0..."+tempValue);
		columnName=st.nextToken();
		System.out.println("1..."+columnName);
		for(String str: colNames)
		{
			if(str.equalsIgnoreCase(columnName))
				break;
			columnIndex++;
		}
		operator=st.nextToken();
		System.out.println("1..."+operator);
		columnValue=st.nextToken();
		System.out.println("1..."+columnValue);
		try  
	    {  
	       Integer.parseInt( columnValue );  
	       value=InstantiateColumnarFile.setKeyClass(value, 0, columnValue);
	    }  
	    catch( Exception e)  
	    {  
	    	value=InstantiateColumnarFile.setKeyClass(value, 1, columnValue);
	    } 
	}
	public static void main(String[] args) {
		//
    	ArrayList <String> left;
    	ArrayList <String> right;
		types = new AttrType[4];
		types[0] = new AttrType(AttrType.attrString);
		types[1] = new AttrType(AttrType.attrString);
		types[2] = new AttrType(AttrType.attrInteger);
		types[3] = new AttrType(AttrType.attrInteger);
		try
		{
		while(choice!=10)
		{
	
		System.out.println("Please select the operation to perform from below menu");
		System.out.println("1. Create a New Database");
		System.out.println("2. Open already existing database");
		System.out.println("*****For all the below operations please open db first*****");
		System.out.println("3. Insert Values in a database/create a columnar file in db");
		System.out.println("4. Columnar Index Scan");
		System.out.println("5. Columnar Nested Loop Joins");
		System.out.println("6. Columnar Bitmap Equi Joins");
		System.out.println("7. Columnar Sort");
		System.out.println("8. Columnar Duplicate Elimination");
		System.out.println("9. Exit closing Db");
		
		choice = getIntInput();
		
		
	    
	    switch (choice)
	    {
	    case 1:
	    	SystemDefs.MINIBASE_RESTART_FLAG = false;
	    	System.out.println("Provide the Database Name");
	    	columnDbName = getStringInput();
	    	System.out.println("Provide the buffer Size");
	    	numBuf = getStringInput();
	    	sysdef = new SystemDefs(columnDbName,10000,Integer.parseInt(numBuf),"Clock");
	    	SystemDefs.MINIBASE_RESTART_FLAG = true;
	    	break;
	    case 2:
	    	System.out.println("Provide the Database Name");
	    	columnDbName = getStringInput();
	    	System.out.println("Provide the buffer Size");
	    	numBuf = getStringInput();
	    	sysdef = new SystemDefs(columnDbName,10000,Integer.parseInt(numBuf),"Clock");    	
	    	break;
	    case 3:
	    	try
	    	{
	    	System.out.println("Provide file name to batch insert");
	    	batchInsertFileName = getStringInput();
	    	System.out.println("Provide the Columnar File name");
	    	columnarFileName =  getStringInput();
	    	System.out.println("Provide the number of columns");
	    	noOfCols = getStringInput();
	    	BatchInsert.batchInsert(batchInsertFileName, columnDbName, columnarFileName, noOfCols);
	    	}
	    	catch(Exception e)
	    	{
	    		e.printStackTrace();
	    		System.out.println("Database Not Created..");
	    	}
	    	break;
	    case 4:
	    	System.out.println("Provide the Columnar File name");
	    	columnarFileName = getStringInput();
	    	cInfo = new  ColumnarFileInfo(columnarFileName+".hdr");
	    	f=new Columnarfile(columnarFileName, 4, types);
	    	cInfo = f.getColumnarFileInfo(columnarFileName+".hdr");
			colNames = cInfo.getColumnNames();
			f.setColumnNames(colNames);
			
			for(String str: colNames)
			{
				if(str.equalsIgnoreCase(columnName))
					break;
				columnIndex++;
			}
			
			short [] str_sizes = {};
			btree.KeyClass [] values = new btree.KeyClass[4];
			String [] operator = new String[4];
			
			
			String [] operand= new String[4];
			String [] conditions = new String[4];
			ArrayList projections = new ArrayList();
			
			operand[0] = "A";
			operand[1] = "B";
			operand[2] = "C";
			
			values[0] = new btree.StringKey("Delaware");
			values[1] = new btree.StringKey("Idaho");
			//values[2] = new btree.IntegerKey(9);
			
			conditions[0] = "or";
			//conditions[1] = "and";
			
			operator[0] = "=";
			operator[1] = "=";
			operator[2] = "=";
			
			projections.add("A");
			projections.add("B");
			
			String relName = "";
			int [] fldNum = {1,2,3};
			IndexType [] index = new IndexType[4] ;
			String [] indName = new String[4];
			
			index[0] = new IndexType(IndexType.Bitmap);
			index[1] = new IndexType(IndexType.B_Index);
			//index[2] = new IndexType(IndexType.B_Index);
			
			indName[0] = "bitmap.ADelaware";
			indName[1] = "btreeB";
			//indName[2] = "btreeC";

			boolean indexOnly = false;
			
			
	    	ColumnarIndexScan cis = new ColumnarIndexScan(relName, fldNum, index, indName, types, str_sizes,operand,values,operator, indexOnly, f, conditions, projections);
	    	break;
	    case 5:
	    	break;
	    case 6:
    	String columnarFileName1=null,columnarFileName2=null, joinConstraint, joinValue;
    	System.out.println("\n\nProvide Inputs for Columnar Bitmap Equi-Joins:");
    	System.out.println("\nEnter the Left Columnar File Name: ");
    	columnarFileName1 = getStringInput();
    	System.out.println("\nEnter the Right Columnar File Name: ");
    	columnarFileName2 = getStringInput();
    	System.out.println("\nEnter the Equality Join Constraint: ");
    	joinConstraint = getStringInput();
    	System.out.println("\nEnter the Value Type of Column selected for join: ");
    	joinValue = getStringInput();
    	if(joinValue.equalsIgnoreCase("Integer"))
    		joinValue="0";
    	int lProj=0, rProj=0;
    	System.out.println("\nEnter the number of projections for Left Columnar File: ");
    	lProj = Integer.parseInt(getStringInput());
    	System.out.println("\nEnter the number of projections for Right Columnar File: ");
    	rProj = Integer.parseInt(getStringInput());
    	left=new ArrayList<String>();
    	right=new ArrayList<String>();
    	System.out.println("\nProjections for Left Columnar File: ");
    	for(int i=0;i<lProj;i++)
    	{
	    	System.out.println("\nEnter the Column Name "+(i+1)+": ");
    		left.add(getStringInput());
    	}
    	System.out.println("\nProjections for Right Columnar File: ");
    	for(int i=0;i<rProj;i++)
    	{
	    	System.out.println("\nEnter the Column Name "+(i+1)+": ");
    		right.add(getStringInput());
    	}
		cJoin=new ColumnarBitmapEquiJoins(columnDbName, columnarFileName1, columnarFileName2, joinConstraint, joinValue, numBuf,left, right);
		cJoin.join();
    	cJoin=null;
    	left=null;
    	right=null;
    	break;
	    case 7:
	    	System.out.println("Provide the Columnar File name");
	    	columnarFileName = getStringInput();
	    	System.out.println("Enter field number to be sorted on");
	    	String fldNo = getStringInput();
	    	System.out.println("Enter sort order( 1 = Ascending 2 = Descending");
	    	String order = getStringInput();
	    	cInfo = new  ColumnarFileInfo(columnarFileName+".hdr");
	    	f=new Columnarfile(columnarFileName, 4, types);
	    	cInfo = f.getColumnarFileInfo(columnarFileName+".hdr");
	    	colNames = cInfo.getColumnNames();
	    	f.setColumnNames(colNames);
	    	
	    	TupleOrder sort_order=null;
	    	if(Integer.parseInt(order)==1)
	    		sort_order = new TupleOrder(TupleOrder.Ascending);
	    	else if(Integer.parseInt(order)==2)
	    		sort_order = new TupleOrder(TupleOrder.Descending);
	    	
	    	new TupleOrder(TupleOrder.Ascending);
			int  strCount =0;
			short[] strSizes = new short[f.getnumColumns()];
			int sortFldLength =0;
			if(f.getAttrType()[Integer.parseInt(fldNo)].attrType==AttrType.attrInteger)
				sortFldLength = 4;
			if(f.getAttrType()[Integer.parseInt(fldNo)].attrType==AttrType.attrString)
				sortFldLength = Size.STRINGSIZE;
			for (AttrType attr: f.getAttrType())
			{
				if (attr.attrType == AttrType.attrString)
				{
					strSizes[strCount] =(short) Size.STRINGSIZE;
				}
				if (attr.attrType == AttrType.attrInteger)
				{
					strSizes[strCount] = 0;
				}
				strCount++;
			}
			Tuple record = new Tuple();
			try{
				ColumnarSort cs = new ColumnarSort(f.getAttrType(), (short)f.getnumColumns(), strSizes, f, Integer.parseInt(fldNo), sort_order, sortFldLength, 10);
				record.setTupleMetaData(f.getTupleLength(), (short)f.getnumColumns(), f.getFldOffset());
				
				int i = 1;
				while((record = cs.get_next()) != null)
				{
					
					record.setTupleMetaData(f.getTupleLength(), (short)f.getnumColumns(), f.getFldOffset());
					System.out.print("Record:"+i++);
					record.print(f.getAttrType());
				}
				
				cs.close();
			}catch(Exception e)	{
				e.printStackTrace();
			}
	    	break;
	    case 8:
	    	System.out.println("Provide the Columnar File name");
	    	columnarFileName = getStringInput();
	    	
	    	cInfo = new  ColumnarFileInfo(columnarFileName+".hdr");
	    	f=new Columnarfile(columnarFileName, 4, types);
	    	cInfo = f.getColumnarFileInfo(columnarFileName+".hdr");
	    	colNames = cInfo.getColumnNames();
	    	f.setColumnNames(colNames);
	    	sort_order = new TupleOrder(TupleOrder.Ascending);
			strCount =0;
			strSizes = new short[f.getnumColumns()];
			
			for (AttrType attr: f.getAttrType())
			{
				if (attr.attrType == AttrType.attrString)
				{
					strSizes[strCount] =(short) Size.STRINGSIZE;
				}
				if (attr.attrType == AttrType.attrInteger)
				{
					strSizes[strCount] = 0;
				}
				strCount++;
			}
			record = new Tuple();
			try{
				ColumnarDuplElim cd = new ColumnarDuplElim(f.getAttrType(), (short)f.getnumColumns(), strSizes, columnarFileName, 10, false);
				record = new Tuple();
				record.setTupleMetaData(f.getTupleLength(), (short)f.getnumColumns(), f.getFldOffset());
				int i =1;
				while((record = cd.get_next()) != null)
				{
					
					record.setTupleMetaData(f.getTupleLength(), (short)f.getnumColumns(), f.getFldOffset());
					System.out.print("DUP Record:"+i++);
					record.print(f.getAttrType());
				}
				cd.close();
			}catch(Exception e)	{
				e.printStackTrace();
			}
	    	break;
	    
	    case 9: break;
	    
	    default: System.out.println("Wrong option selected..");
	    break;
	    	
	 
	    }
		
		}
	}
		catch(Exception e)
		{
			//e.printStackTrace();
		}
	}
	
	private static int getIntInput()
	{
		int choice = 0;
		BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
	    
		String s="";
	    try {
	    
	    	s=in.readLine();
	    	choice = Integer.parseInt(s);
	    	
	    }
	    catch (NumberFormatException e) {
	    	System.out.println("***********Please provide a proper input***********");
	    } catch (IOException e) {
	    	System.out.println("***********Please provide a proper input***********");
		}
	    return choice;
	}
	
	private static String getStringInput()
	{
		int choice = 0;
		BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
	    
		String s="";
	    try {
	    
	    	s=in.readLine();
	    		    	
	    }
	    catch (NumberFormatException e) {
	    	System.out.println("***********Please provide a proper input***********");
	    } catch (IOException e) {
	    	System.out.println("***********Please provide a proper input***********");
		}
	    return s;
	}

}
